package com.koron.rating.classify.services;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.koron.bean.base.Constants;
import com.koron.bean.base.Response;
import com.koron.bean.system.org.OrgBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.CommonUtils;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.rating.change.bean.UnitCheckPo;
import com.koron.rating.classify.bean.RatingUnitBatchDto;
import com.koron.rating.classify.bean.RatingUnitBean;
import com.koron.rating.classify.bean.RatingUnitSortDto;
import com.koron.rating.classify.bean.Select;
import com.koron.rating.classify.mapper.RatingUnitMapper;
import com.koron.rating.enums.UnitSortTypeEnum;
import com.koron.rating.enums.UnitTypeEnum;
import com.koron.rating.units.RatingUnits;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

import static com.koron.rating.enums.UnitTypeEnum.*;

/**
 * @Author: rocky
 * @Date: 2022/1/6 15:54
 */
@Service
public class UnitClassifyService {

    private EamUser getEamUser() {
        return ThreadLocalContext.get();
    }

    @Autowired
    private OrgCacheUtils orgCacheUtils;

    @Autowired
    private SystemFeignService systemFeignService;

    @TaskAnnotation("insert")
    public Response insert(SessionFactory factory, RatingUnitBean ratingunit) {

        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        if (StringUtils.isEmpty(ratingunit.getParentId())) {
            // 没有父级，说明是根节点
            ratingunit.setParentId(Constants.DEVICE_TREE_ROOT_CODE);
        }
        ratingunit.setId(CodeTools.getCode32());
        RatingUnitBean parent = mapper.selectByPrimaryKey(ratingunit.getParentId());
        // 如果根节点不存在，则设置默认根节点
        if (Objects.isNull(parent)) {
            ratingunit.setParentName("0");
            ratingunit.setLevel(1);
            ratingunit.setFullPathCode(ratingunit.getId());
            ratingunit.setFullPathName(ratingunit.getName());
        } else {
            ratingunit.setParentName(parent.getName());
            // 父级level+1
            ratingunit.setLevel(parent.getLevel() + 1);
            ratingunit.setFullPathCode(parent.getFullPathCode() + "/" + ratingunit.getId());
            ratingunit.setFullPathName(parent.getFullPathName() + "/" + ratingunit.getName());
            //单元、设备、部件 级带上 父级单位id
            if (Lists.newArrayList("4", "5", "6").contains(ratingunit.getUnitType())) {
                ratingunit.setDeptId(parent.getDeptId());
                ratingunit.setDeptName(parent.getDeptName());
            }
        }
        if (parent!=null && ratingunit.getUnitType().compareTo(parent.getUnitType()) == -1) {
            return Response.fail("单元类型选择错误");
        }
        // 获取该层级的最大编码
        Integer maxLevelCode = mapper.getMaxLevelCodeByLevel(ratingunit.getLevel());
        maxLevelCode = maxLevelCode == null ? 1 : maxLevelCode + 1;
        ratingunit.setLevelCode(maxLevelCode);
        ratingunit.setSort(maxLevelCode);

        if ("0".equals(ratingunit.getParentId())) {
            ratingunit.setLevelPath(maxLevelCode + "");
        } else {
            String levelPath = mapper.queryLevelPathById(ratingunit.getParentId());
            ratingunit.setLevelPath(levelPath + "/" + maxLevelCode);
        }
        mapper.insert(ratingunit);
        return Response.success(ratingunit.getId());
    }

    /**
     * 根据变更单id、类型 查重复数据
     * @param factory
     * @param unitTypelist 类型s
     * @param det          新增数据
     * @param id          更新Id
     *                    单元、设备、部件 不允许重复
     */
    @TaskAnnotation("checkRepeat")
    public void checkRepeat(SessionFactory factory, List<String> unitTypelist, List<UnitCheckPo> det, String id) {
        ArrayList<String> sbjlist = CollUtil.newArrayList(LEVEL4.getValue(), LEVEL5.getValue(), LEVEL6.getValue());
        //新增类型是否 是单元、设备、部件
        if (det.stream().anyMatch(d->sbjlist.contains(d.getUnitType()))) {
            unitTypelist = sbjlist;
        }
        // 相应变更id 根据层级 获取 已存在 的 （部门)、（单位）、（单元、设备、部件）
        List<String> eqIdlisted = factory.getMapper(RatingUnitMapper.class).queryEquipmentIdByUnitTypeIn(unitTypelist, id);
        Iterator<UnitCheckPo> iterator = det.iterator();
        while (iterator.hasNext()) {
            UnitCheckPo dto = iterator.next();
            if (eqIdlisted.contains(dto.getId())) {
                cn.hutool.core.lang.Assert.isFalse(true, StrUtil.format("{} 存在重复"), dto.getName());
            }
        }
    }

    /**
     * 校验单位
     * @param factory
     * @param id          组织id
     */
    @TaskAnnotation("checkDept")
    public void checkDept(SessionFactory factory, String id) {
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        List<OrgBean> orgBeanList = mapper.queryOrg(CollUtil.newArrayList(id));
        String levelPath = orgBeanList.get(0).getLevelPath();
        List<String> split = StrUtil.split(levelPath, "/");
        split.remove(id);//移除自身
        List<OrgBean> checketlist = mapper.queryOrg(split);
        for (OrgBean orgBean : checketlist) {
            cn.hutool.core.lang.Assert.isFalse(orgBean.getLevel().equals("2"), "被选组织父节点不能含有部门级");
        }
    }

    @TaskAnnotation("insertBatch")
    public Response insertBatch(SessionFactory factory, RatingUnitBatchDto dto) {
        List<RatingUnitBean> det = new ArrayList<>();
        dto.getDet().stream().forEach(d -> {
            det.add(Convert.convert(RatingUnitBean.class, d));
        });

        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        if (StringUtils.isEmpty(dto.getParentId())) {
            // 没有父级，说明是根节点
            det.stream().forEach(d -> {
                d.setParentId(Constants.DEVICE_TREE_ROOT_CODE);
            });
        }
        RatingUnitBean parent = mapper.selectByPrimaryKey(dto.getParentId());

        for (RatingUnitBean d : det) {
            d.setId(CodeTools.getCode32());
//            d.setUnitType(dto.getUnitType());//单元类型
            d.setParentId(dto.getParentId());//父节点
            d.setParentName(parent.getName());
            // 父级level+1
            d.setLevel(parent.getLevel() + 1);
            d.setFullPathCode(parent.getFullPathCode() + "/" + d.getId());
            d.setFullPathName(parent.getFullPathName() + "/" + d.getName());
        }

        if (dto.getUnitType().compareTo(parent.getUnitType()) == -1) {
            return Response.fail("单元类型选择错误");
        }
        // 获取该层级的最大编码
        Integer maxLevelCode = mapper.getMaxLevelCodeByLevel(parent.getLevel() + 1);//该批次都同个父级下的层级
        maxLevelCode = maxLevelCode == null ? 1 : maxLevelCode + 1;
        for (RatingUnitBean d : det) {
            d.setLevelCode(maxLevelCode);
            d.setSort(maxLevelCode);
            d.setLevelPath(parent.getLevelPath() + "/" + maxLevelCode);
            maxLevelCode = maxLevelCode + 1;
        }
        mapper.batchInsert(det);

        return Response.success(det.get(0).getId());
    }


    @TaskAnnotation("update")
    public Response update(SessionFactory factory, RatingUnitBean ratingunit) {

        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        // 数据库未更新时的设备信息
        RatingUnitBean origin = mapper.selectByPrimaryKey(ratingunit.getId());
        if (!StringUtils.equals(ratingunit.getParentId(), "0")) {
            RatingUnitBean parent = mapper.selectByPrimaryKey(ratingunit.getParentId());
            if (ratingunit.getUnitType().compareTo(parent.getUnitType()) == -1) {
                return Response.fail("单元类型选择错误");
            }
        }
        // 更新当前节点的所有子节点的parent_name
        mapper.updateParentNameById(ratingunit.getId(), ratingunit.getName());
        if (!StringUtils.equals(origin.getName(), ratingunit.getName())) {
            // 如果名字更新，则更新full_path_name
            mapper.updateFullPathName(origin.getName(), ratingunit.getName(), ratingunit.getId());
        }
        mapper.updateByPrimaryKeySelective(ratingunit);
        return Response.success();
    }

    @TaskAnnotation("delete")
    public Response delete(SessionFactory factory, String id) {
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        if (mapper.countChildren(id) > 0) {
            return Response.fail("该节点下还有子节点，不能删除");
        }
        mapper.delete(id);
        return Response.success();
    }

    @TaskAnnotation("getById")
    public Response<RatingUnitBean> getById(SessionFactory factory, String id) {
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        RatingUnitBean ratingunit = mapper.selectByPrimaryKey(id);
        Assert.notNull(ratingunit, "单元不存在");
        ratingunit.setDeptName(orgCacheUtils.getOrgNameById(ratingunit.getDeptId()));
        return Response.success(ratingunit);
    }

    @TaskAnnotation("getTreeLazy")
    public Response getTreeLazy(SessionFactory factory, String parentId) {
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        if (StringUtils.isEmpty(parentId)) {
            parentId = "02000000000001";
        }
        List<RatingUnitBean> list = mapper.list(parentId, null);
        // 获取权限
        ArrayList<String> units = RatingUnits.getPower(getEamUser());
        list = list.stream().filter(l -> units.contains(l.getDeptId())).collect(Collectors.toList()); // 可以看权限配置的范围
//        list = list.stream().filter(r -> r.getDeptId().equals(getEamUser().getDeptId())).collect(Collectors.toList()); //只可以看自己部门的
        list.stream().forEach(equipment -> equipment.setChildrenNum(mapper.countChildren(equipment.getId())));
        return Response.succ(list);
    }


    @TaskAnnotation("getFloor")
    public Response<List> getFloor(SessionFactory factory, String parentId, String id) {
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        List<Select> selects = getSelects();
        // 当前id和父id都为空，说明是新增根节点，返回全部
        if (StringUtils.isAllEmpty(parentId, id)) {
            return Response.success(selects);
        }
        // 父级设备
        RatingUnitBean ratingunit = mapper.selectByPrimaryKey(parentId);
        // 当前id为空，父id不为空，说明是新增子节点
        if (StringUtils.isEmpty(id)) {
            selects.stream().forEach(select -> select.setDisabled(ratingunit.getUnitType().compareTo(select.getValue()) > 0));
            return Response.succ(selects);
        }
        List<RatingUnitBean> children = mapper.list(id, null);
        String s = children.size() > 0 ? children.stream().map(RatingUnitBean::getUnitType).min((x, y) -> x.compareTo(y)).get() : "0";
        selects.stream().forEach(select -> select.setDisabled((ratingunit != null && ratingunit.getUnitType().compareTo(select.getValue()) > 0) || (!"0".equals(s) && s.compareTo(select.getValue()) < 0)));
        return Response.succ(selects);
    }

    @TaskAnnotation("searchByName")
    public Response<List<RatingUnitBean>> searchByName(SessionFactory factory, String name, String deptId) {
        if (StringUtils.isEmpty(name)) {
            return Response.succ(Collections.emptyList());
        }
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        List<RatingUnitBean> result = mapper.listBydeptId(deptId, name);
        return Response.succ(result);
    }

    /**
     * 获取所有层级下拉
     *
     * @return
     */
    private static List<Select> getSelects() {
        List<Select> list = Lists.newArrayList();
        for (UnitTypeEnum item : values()) {
            Select select = new Select();
            select.setLabel(item.getLabel());
            select.setValue(item.getValue());
            select.setDisabled(false);
            list.add(select);
        }
        return list;
    }

    @TaskAnnotation("getParentIds")
    public Response<List<String>> getParentIds(SessionFactory factory, String id) {
        List<String> list = new LinkedList<>();
        RatingUnitBean equipment = getById(factory, id).getData();
        while (!StringUtils.equals(equipment.getParentId(), "0")) {
            equipment = getById(factory, equipment.getParentId()).getData();
            list.add(0, equipment.getId());
        }
        return Response.succ(list);
    }

    /**
     * 获取同组织下，最左上的设备台账
     *
     * @param factory
     * @param deptId
     * @return
     */
    @TaskAnnotation("getLeftUpperRatingUnitByDeptId")
    public Response getLeftUpperRatingUnitByDeptId(SessionFactory factory, String deptId) {
        RatingUnitBean equipment = null;
        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        if (StringUtils.isBlank(deptId)) {
            deptId = ThreadLocalContext.get().getDeptId();
            OrgBean orgBean = CommonUtils.ok(systemFeignService.querySingleOrg(deptId));
            Assert.notNull(orgBean, "用户所在组织不存在");
            equipment = mapper.getLeftUpperRatingByDeptId(orgBean.getId());
            if (equipment != null) {
                return Response.ok(equipment);
            }
        } else {
            RatingUnitBean unit = mapper.getLeftUpperRatingByDeptId(deptId);
            if (ObjectUtil.isNull(unit)) {
                unit = mapper.getLeftUpperEquipmentByDeptId(deptId);
            }
            return Response.ok(unit);
        }
        return Response.ok(equipment);
    }


    @TaskAnnotation("changeSort")
    public Response<String> changeSort(SessionFactory factory, RatingUnitSortDto dto) {

        RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
        //上移
        if (dto.getSortType().equals(UnitSortTypeEnum.UP.getLabel())) {
            List<RatingUnitBean> minlist = mapper.queryByParentIdAndSortBefore(dto.getParentId(), dto.getSort());
            if (CollUtil.isNotEmpty(minlist)) {
                RatingUnitBean bean = minlist.get(minlist.size() - 1);//它的上一位
                //交换序号
                mapper.updateSortById(bean.getSort(), dto.getId());//把上一位的序号哥给它
                mapper.updateSortById(dto.getSort(), bean.getId());//把自己的序号给上一位
            }
        }
        if (dto.getSortType().equals(UnitSortTypeEnum.DOWN.getLabel())) {
            List<RatingUnitBean> maxlist = mapper.queryByParentIdAndSortAfter(dto.getParentId(), dto.getSort());
            if (CollUtil.isNotEmpty(maxlist)) {
                RatingUnitBean bean = maxlist.get(0);//它的下一位
                //交换序号
                mapper.updateSortById(bean.getSort(), dto.getId());//把下一位的序号给自己
                mapper.updateSortById(dto.getSort(), bean.getId());//把自己的序号给下一位
            }
        }

        return Response.succ(dto.getParentId());
    }

}
